package edu.krazy.client;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Formatter;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;

import edu.krazy.common.BasicClientMessage;
import edu.krazy.common.ClientState;
import edu.krazy.common.KrazyKartsConfig;
import edu.krazy.common.MessageType;
import edu.krazy.common.PositionInfo;

public class KrazyKartsMain implements IOnServerMessage {
	
	private BasicClient mClient;
	
	private JFrame mMain;
	private JPanel mUsernamePanel;
	private Formatter out;
	private IOnKrazyListener mListener;
	
	

	public JFrame getMain() {
		return mMain;
	}

	public KrazyKartsMain(IOnKrazyListener listener){
		mListener = listener;
		out = new Formatter(System.out);
		mMain = new JFrame("Krazy Karts");
		mMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mMain.setVisible(true);
		
		showUsernamePane();
	}
	
	/************ GET USERNAME WINDOWS & LISTENERS!!************/
	
	private static final String ACTION_CLICK_START = "click_start";
	private JTextField mUserField;
	
	private void showUsernamePane(){
		if(mUsernamePanel == null){
			mUsernamePanel = new JPanel();
			JLabel label = new JLabel("Enter your username:");
			mUsernamePanel.add(label);
			
			mUserField = new JTextField(20);
			mUsernamePanel.add(mUserField);
			
			JButton button = new JButton("Start");
			button.setMnemonic(KeyEvent.VK_ENTER);
			button.setActionCommand(ACTION_CLICK_START);
			button.addActionListener(mActionListener);
			mUsernamePanel.add(button);
		}
		mMain.setJMenuBar(null);
		mMain.setContentPane(mUsernamePanel);
		mMain.pack();
	}
	
	private ActionListener mActionListener = new ActionListener() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
			String username;
			if(e.getActionCommand().equals(ACTION_CLICK_START) && (username = mUserField.getText().trim()).length() > 0){
				mClient = new BasicClient(username, KrazyKartsConfig.SERVER_ADDRESS, KrazyKartsConfig.SERVER_PORT);
				mClient.setListener(KrazyKartsMain.this);
				mClient.start();
			}else if(e.getActionCommand().equals(ACTION_NEW_GAME)){
				showAddGameDialog();
			}else if(e.getActionCommand().equals(ACTION_START_GAME)){
				mClient.addMessage(new BasicClientMessage(MessageType.READY_GAME));
				readyGameEngine();
			}
			else if(e.getActionCommand().equals(ACTION_LEAVE_GAME)){
				mClient.addMessage(new BasicClientMessage(MessageType.LEAVE_GAME));
				//readyGameEngine();
			}
		}
	};
	
	
	/************END GET USERNAME WINDOWS & LISTENERS!!************/
	
	
	/************LOBBY WINDOWS & LISTENERS!!************/
	private static final String ACTION_NEW_GAME = "new_game"; 
	
	private JScrollPane mLobbiesView;
	private JList mLobbiesList;
	private JMenuBar mLobbiesBar;
	private JMenuItem mAddGameMenu;
	
	private void showLobbiesPane(String[] lobbies){
		if(mLobbiesView == null){
			mLobbiesView = new JScrollPane();
			mLobbiesView.setPreferredSize(new Dimension(300, 100));
			mLobbiesList = new JList();
			mLobbiesList.addMouseListener(new MouseAdapter() {
				public void mouseClicked(MouseEvent e) {
			        if (e.getClickCount() == 2) {
			            int index = mLobbiesList.locationToIndex(e.getPoint());
			            mClient.addMessage(new BasicClientMessage(MessageType.JOIN_GAME, mLobbiesList.getModel().getElementAt(index)));
			         }
			    }
			});
			
			mLobbiesView.getViewport().setView(mLobbiesList);
			
			mLobbiesBar = new JMenuBar();
			
			mAddGameMenu = new JMenuItem("Create Game");
			mAddGameMenu.setActionCommand(ACTION_NEW_GAME);
			mAddGameMenu.addActionListener(mActionListener);
			mLobbiesBar.add(mAddGameMenu);
		}
		mLobbiesList.setListData(lobbies);
		mMain.setJMenuBar(mLobbiesBar);
		mMain.setContentPane(mLobbiesView);
		mMain.pack();
	}
	
	private void showAddGameDialog(){
		String gameName = (String)JOptionPane.showInputDialog(mMain,
																"Game name:",
																"Create Game",
																JOptionPane.PLAIN_MESSAGE);
		;
		if(gameName!= null && (gameName = gameName.trim()).length()> 0){
			mClient.addMessage(new BasicClientMessage(MessageType.CREATE_GAME, gameName));
		}
	}
	/************END LOBBY WINDOWS & LISTENERS!!************/
	
	/************GAME SETUP WINDOWS & LISTENERS!!************/
	private static final String ACTION_START_GAME = "start_game"; 
	private static final String ACTION_LEAVE_GAME = "leave_game"; 
	
	private JScrollPane mGameSetupView;
	private JList mPlayerList;
	private JMenuBar mGameBar;
	private JMenuItem mGameOption;
	private boolean mIsCreator;
	
	private void showSetupGamePane(String[] users){
		out.format("showSetupGamePane");
		for (int i = 0; i < users.length; i++) {
			out.format("%s", users[i]);
		}
		
		if(mGameSetupView == null){
			mGameSetupView = new JScrollPane();
			mGameSetupView.setPreferredSize(new Dimension(300,100));
			
			mPlayerList = new JList();
			mPlayerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			mPlayerList.setLayoutOrientation(JList.VERTICAL);
			mGameSetupView.getViewport().setView(mPlayerList);
			
			mGameBar = new JMenuBar();
			mGameOption = new JMenuItem();
			mGameOption.addActionListener(mActionListener);
			mGameBar.add(mGameOption);
		}
		if(mIsCreator){
			mGameOption.setActionCommand(ACTION_START_GAME);
			mGameOption.setText("Start Game");
		}else{
			mGameOption.setActionCommand(ACTION_LEAVE_GAME);
			mGameOption.setText("Exit Game");
		}
		mMain.setJMenuBar(mGameBar);
		mPlayerList.setListData(users);
		
		mMain.setContentPane(mGameSetupView);
		mMain.pack();
	}
	
	private void refreshPlayerList(String[] users){
		if(mPlayerList != null){
			mPlayerList.setListData(users);
		}
	}
	/************END GAME SETUP WINDOWS & LISTENERS!!************/
	
	/************GAME WINDOWS & LISTENERS!!************/
	private KrazyModel mModel;
	
	//TODO MEMO
	//private engineCanvas...
	private void readyGameEngine(){
		out.format("readyGameEngine\n");
		if(mListener != null){
			mListener.onReadyGameEngine(mClient);
		}
		mClient.addMessage(new BasicClientMessage(MessageType.READY_PLAYER));
	}
	/**
	 * Called when the server sends everybody is ready...
	 */
	private void startGame(String[] users){
		out.format("startGame\n");
		mModel = new KrazyModel(users);
		if(mListener != null){
			mListener.onStartGameEngine(mModel);
		}
	}
	/**
	 * @param args
	 */
	/*public static void main(String[] args) {
		new KrazyKartsMain();
	}*/


	@Override
	public void handleServerMessage(int messageType, ObjectInputStream stream) {
		switch (messageType) {
		case MessageType.GAME_LIST:
			try {
				showLobbiesPane(stream.readUTF().split(","));
			} catch (IOException e) {
				e.printStackTrace();
			}
			break;
		case ClientState.CONNECTED_TO_LOBBY:
			mClient.setClientState(messageType);
			break;
		case MessageType.GAME_CREATED:
			mIsCreator = true;
			break;
		case MessageType.PLAYER_LIST:
			try {
				refreshPlayerList(stream.readUTF().split(","));
			} catch (IOException e) {
				e.printStackTrace();
			}
			break;
		case MessageType.JOINED_GAME:
			try {
				showSetupGamePane(stream.readUTF().split(","));
			} catch (IOException e) {
				e.printStackTrace();
			}
			break;
		case MessageType.READY_GAME:
			readyGameEngine();
			break;
		case MessageType.START_GAME:
			try {
				startGame(stream.readUTF().split(","));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		case MessageType.BROADCAST_POSITIONS:
			try {
				mModel.updateClientPosition(stream.readUTF(), (PositionInfo)stream.readObject());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		default:
			break;
		}
		
	}

}
